package MasterManagers.utils;

import MasterManagers.SocketManager.SocketThread;
import MasterManagers.TableManager;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Slf4j
public class ServiceStrategyExecutor {

    private TableManager tableManager;

    public ServiceStrategyExecutor(TableManager tableManager) {
        this.tableManager = tableManager;
    }

    public boolean hasServer(String hostUrl) {
        return tableManager.hasServer(hostUrl);
    }

    public void execStrategy(String hostUrl, StrategyTypeEnum type) {
        try {
            switch (type) {
                case RECOVER:
                    execRecoverStrategy(hostUrl);
                    break;
                case INVALID:
                    execInvalidStrategy(hostUrl);
                    break;
                case ADD:
                    execAddStrategy(hostUrl);

            }
        } catch (Exception e) {
            log.warn(e.getMessage(), e);
        }
    }

    /***
     *
     * @param hostUrl
     * master 先找到一个接替的Region，作为bestInet
     * 对于每一张表，master要联系他的副region，告诉副region新的bestInet和表名字，使得表能够再次备份
     * 发送给副Region的语句格式：[master] copy ip tableName
     * 这里首先要遍历挂掉Region的TableList
     */

    private void execAddStrategy(String hostUrl){
        Pattern pattern = Pattern.compile("(\\d.*\\d)"); // 正则表达式匹配一个或多个数字，可能之后是小数点和一些数字
        Matcher matcher = pattern.matcher(hostUrl);
        if (matcher.find()) { // 如果找到匹配的部分
            hostUrl = matcher.group(); // 这就是匹配的数字部分
        }
        else{
            return;
        }
//        SocketThread socketThread = tableManager.getSocketThread(hostUrl);
        if(!tableManager.getServerList().contains(hostUrl))
            tableManager.addServer(hostUrl);
//        System.out.println("result = " + tableManager.hasServer(hostUrl));
//        socketThread.send("recover");
    }

    private void execInvalidStrategy (String hostUrl) throws InterruptedException {
        // 将失效region的所有表都执行一次负载均衡算法，找出新的region地址，分别向所有的client和新的region发送消息,以下为每个表的操作
        System.out.println("Invalid: "  + hostUrl);
        List<String> tableList = tableManager.getTableList(hostUrl);
        if (tableList.isEmpty()){
            tableManager.deleteServer(hostUrl);
            return ;
        }
        if (tableManager.serverNum() <= 2){
            System.out.println("It has only" + tableManager.serverNum() + " region servers, no invalid strategy can be executed.");
            System.out.println("The remaining region server is : " + tableManager.getUniqueServer());
            String region = tableManager.getUniqueServer();
            tableManager.exchangeTable(region);
            tableManager.deleteServer(hostUrl);
            return ;
        }
        for (String table: tableList){
            String newIP = tableManager.getIdealServer(hostUrl, table); //选出来的region的ip:port
            //向所有client发消息
//            for(String client : tableManager.getClient()){
//                for(SocketThread s : this.tableManager.getSocketThread(client)){
//                    s.send("<M2C>[7]" + table + "," + hostUrl + "," + newIP);
//                }
//            }
            List<String> subIPs = tableManager.getInetAddress(table);
            System.out.println("subIPs:");
            System.out.println(subIPs);
            subIPs.remove(hostUrl);
            //向region发消息
            SocketThread s = tableManager.getSocketThread(newIP).get(0);
            s.send("<M2R>[5]" + table + "," + subIPs.get(0));
            Thread.sleep(1000);
            tableManager.addTable(table, newIP);
        }

        tableManager.deleteServer(hostUrl);
    }

    //恢复策略,主节点给从节点发消息，让该从节点删除所有旧的表,从节点重新上线，
    private void execRecoverStrategy(String hostUrl) {
        System.out.println("Recover: " + hostUrl);
        tableManager.recoverServer(hostUrl);
//        SocketThread socketThread = tableManager.getSocketThread(hostUrl);
        //实际上不需要这个，因为region上线后自动删除
//        socketThread.send("<M2R>[8]");
    }
}


